#pragma once

#include <iostream>
#include <fstream>
#include <vector>
#include "json.hpp"
#include "question.hpp"
#include "student.hpp"


class DataMgr
{
public:
	static DataMgr& getInstance()
	{
		static DataMgr inst;
		return inst;
	}

	void loadQuestions()
	{
		std::ifstream ifs("question.json");
		if (!ifs.is_open())
			throw std::runtime_error("ifstream open error");

		nlohmann::json js = nlohmann::json::parse(ifs);

		for (int i = 0; i < js.size(); i++)
		{
			nlohmann::json item = js[i];

			std::string type = item["type"].get<std::string>();
			if (type == "choice")
			{
				ChoiceQuestion* cq = new ChoiceQuestion;
				cq->fromJson(item);
				_questions.push_back(cq);
			}
			else if (type == "truefalse")
			{
				TrueFalseQuestion* tq = new TrueFalseQuestion;
				tq->fromJson(item);
				_questions.push_back(tq);
			}
			else
			{
				throw std::runtime_error("unkown question type");
			}
		}
	}

	void persistQuestions()
	{
		std::ofstream ofs("question.json");
		if (!ofs.is_open())
			throw std::runtime_error("ofstream open error");

		nlohmann::json js;
		for (const Question* question : _questions)
		{
			nlohmann::json item = question->toJson();
			js.push_back(item);
		}

		std::string str = js.dump();
		ofs.write(str.c_str(), str.size());
	}

	std::vector<Question*>& getQuestions()
	{
		return _questions;
	}

private:
	DataMgr() 
	{
		loadQuestions();
	}

	~DataMgr() 
	{
		persistQuestions();

		for (auto* q : _questions) 
			delete q;
	}

	DataMgr(const DataMgr&) = delete;
	DataMgr& operator=(const DataMgr&) = delete;

	std::vector<Student> _students;
	std::vector<Question*> _questions;
};